package com.laf.manage.listener;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.laf.common.constant.CacheConstants;
import com.laf.common.constant.MQConstant;
import com.laf.common.core.redis.RedisCache;
import com.laf.manage.constant.LostItemStatusConstant;
import com.laf.manage.domain.doc.LostItemDoc;
import com.laf.manage.domain.dto.DynamicCountDTO;
import com.laf.manage.domain.po.*;
import com.laf.manage.enums.ContentTypeEnum;
import com.laf.manage.mapper.es.LostItemEsMapper;
import com.laf.manage.mapper.mp.CommentsMapper;
import com.laf.manage.mapper.mp.StoreMapper;
import com.laf.manage.service.*;
import com.laf.manage.service.impl.DynamicEsService;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class UserListener {

    private final IAuthInfoService authInfoService;

    private final ILostItemService lostItemService;

    private final LostItemEsMapper lostItemEsMapper;

    private final ICommentsService commentsService;

    private final IDynamicService dynamicService;

    private final DynamicEsService dynamicEsService;

    private final IDynamicTagService dynamicTagService;

    private final IStoreService storeService;

    private final StoreMapper storeMapper;

    private final RedisCache redisCache;

    private final CommentsMapper commentsMapper;


    /**
     * 处理删除用户的消息
     * <p>
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(
                    value = MQConstant.USER_DELETE_QUEUE,
                    durable = "true",
                    arguments = @Argument(name = "x-queue-mode", value = "lazy") // 懒加载，减少内存消耗
            ),
            exchange = @Exchange(value = MQConstant.USER_EXCHANGE),
            key = MQConstant.USER_DELETE_ROUTING_KEY
    ))
    public void deleteUserInfo(Long userId) {
        // 1. 删除凭证
        authInfoService.remove(
                Wrappers.<AuthInfo>lambdaQuery()
                        .eq(AuthInfo::getUserId, userId)
        );
        // 2. 删除失物数据
        delLostInfoByUserId(userId);

        // 3. 删除评论
        delCommentsByUserId(userId);


        // 5. 删除动态和动态对应的标签
        delDynamicByUserId(userId);


        // 6. 删除动态对应的收藏
        delStoreByUserId(userId);

    }

    /**
     * 删除动态收藏数据
     *
     * @param userId 用户id
     */
    private void delStoreByUserId(Long userId) {
        // 查询用户的所有收藏信息
        List<Store> storeList = storeService.list(
                Wrappers.<Store>lambdaQuery()
                        .eq(Store::getCreateUserId, userId)
        );
        if (CollUtil.isNotEmpty(storeList)) {
            List<Long> storeIds = storeList.stream().map(Store::getId).collect(Collectors.toList());
            // 删除 mysql 中收藏数量
            storeService.removeBatchByIds(storeIds);

            // 删除缓存中动态的对应的收藏数量
            List<Long> dynamicIds = storeList.stream()
                    .filter(item -> item.getContentType().equals(ContentTypeEnum.DYNAMIC))
                    .map(Store::getContentId)
                    .collect(Collectors.toList());

            // 删除 redis 中动态的收藏数
            for (Long dynamicId : dynamicIds) {
                redisCache.deleteCacheMapValue(CacheConstants.STORE_PREFIX, dynamicId.toString());
            }

            // 查询动态对应的收藏数量
            List<DynamicCountDTO> dynamicCountDTOS = storeMapper.dynamicStoreCountByDynamicIds(dynamicIds);
            Map<String, Integer> storeMap = dynamicCountDTOS.stream()
                    .collect(Collectors.toMap(item -> item.getDynamicId().toString(), DynamicCountDTO::getCount));
            storeMap.forEach((k, v) -> {
                redisCache.setCacheMapValue(CacheConstants.STORE_PREFIX, k, v);
            });

        }
    }

    /**
     * 删除动态数据 mysql + es
     *
     * @param userId 用户id
     */
    private void delDynamicByUserId(Long userId) {
        // 收集动态数据
        List<Dynamic> dynamicList = dynamicService.list(
                Wrappers.<Dynamic>lambdaQuery()
                        .select(Dynamic::getId)
                        .eq(Dynamic::getCreateUserId, userId)
        );
        if (CollUtil.isNotEmpty(dynamicList)) {
            List<Long> dynamicIds = dynamicList.stream()
                    .map(Dynamic::getId)
                    .collect(Collectors.toList());

            // 删除mysql
            dynamicService.removeBatchByIds(dynamicIds);

            // 删除 es
            dynamicEsService.sendDeleteDynamicDoc(dynamicIds);

            // 删除动态的标签
            dynamicTagService.remove(
                    Wrappers.<DynamicTag>lambdaQuery()
                            .in(DynamicTag::getDynamicId, dynamicIds)
            );

        }
    }

    /**
     * 删除评论数据
     *
     * @param userId
     */
    private void delCommentsByUserId(Long userId) {
        List<Comments> commentsList = commentsService.list(
                Wrappers.<Comments>lambdaQuery()
                        .eq(Comments::getCreateUserId, userId)
        );
        if (CollUtil.isNotEmpty(commentsList)) {
            List<Long> commentsIds = commentsList.stream()
                    .map(Comments::getId)
                    .collect(Collectors.toList());

            // 删除mysql
            commentsService.removeBatchByIds(commentsIds);

            // 删除redis 中动态的评论数
            List<Long> dynamicIds = commentsList.stream()
                    .map(Comments::getDynamicId)
                    .collect(Collectors.toList());
            for (Long dynamicId : dynamicIds) {
                redisCache.deleteCacheMapValue(CacheConstants.COMMENTS_PREFIX, dynamicId.toString());
            }

            // 重新获取动态的评论数据
            List<DynamicCountDTO> dynamicCountDTOS = commentsMapper.dynamicCommentCountByDynamicIds(dynamicIds);

            // 重新添加缓存评论数量
            Map<String, Integer> commentMap = dynamicCountDTOS.stream()
                    .collect(Collectors.toMap(item -> item.getDynamicId().toString(), DynamicCountDTO::getCount));
            commentMap.forEach((k, v) -> {
                redisCache.setCacheMapValue(CacheConstants.COMMENTS_PREFIX, k, v);
            });
        }
    }

    /**
     * 删除失物数据
     * 根据失物的状态分别处理：
     * 1 .待审核 、 待提交失物直接删除
     * 2. 待领取  已领取 驳回的 转义到 id 为 1L 的用户上
     *
     * @param userId 用户id
     */
    private void delLostInfoByUserId(Long userId) {
        List<LostItem> lostItemList = lostItemService.list(
                Wrappers.<LostItem>lambdaQuery().eq(LostItem::getCreateUserId, userId)
        );
        if (CollUtil.isNotEmpty(lostItemList)) {
            // 删除数据 待审核 、 待提交失物直接删除
            List<Long> delItemIds = lostItemList.stream()
                    .filter(item -> item.getStatus().equals(LostItemStatusConstant.WAIT_AUDIT)
                            || item.getStatus().equals(LostItemStatusConstant.WAIT_SUBMIT))
                    .map(LostItem::getId)
                    .collect(Collectors.toList());
            if (CollUtil.isNotEmpty(delItemIds)) {
                // 删除mysql
                lostItemService.removeBatchByIds(delItemIds);

                // 删除 es
                lostItemEsMapper.deleteBatchIds(delItemIds);
            }

            // 收集所有需要修改的数据 待领取  已领取 驳回的 转义到 id 为 1L 的用户上
            List<LostItem> updateItemList = lostItemList.stream()
                    .filter(item -> item.getStatus().equals(LostItemStatusConstant.WAIT_PICKED)
                            || item.getStatus().equals(LostItemStatusConstant.PICKED)
                            || item.getStatus().equals(LostItemStatusConstant.REJECTED)
                    ).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(updateItemList)) {
                for (LostItem lostItem : updateItemList) {
                    lostItem.setCreateUserId(1L);
                    lostItem.setCreateBy("10086");
                    lostItem.setUpdateBy("10086");
                }
                // 更新mysql
                lostItemService.updateBatchById(updateItemList);

                // 更新 es
                List<LostItemDoc> lostItemDocs = BeanUtil.copyToList(updateItemList, LostItemDoc.class);
                lostItemEsMapper.updateBatchByIds(lostItemDocs);
            }
        }
    }

}
